package it.tukano.swingdeco.containers;

import it.tukano.collections.LinkedListExt;
import it.tukano.collections.ListExt;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.util.Collection;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

/**
 * A panel that places components in horizontal rows
 * @author utente4
 */
public class JRowPanel extends JPanelExt {

    private static final long serialVersionUID = 0;

    public static JRowPanel newTopAlignedInstance() {
        return new JRowPanel(new BorderLayout(), BorderLayout.NORTH);
    }

    private Box rows = Box.createVerticalBox();

    public JRowPanel(LayoutManager m, Object rowsConstraints) {
        super(m);
        add(rows, rowsConstraints);
    }

    public JRowPanel(LayoutManager layout) {
        super(layout);
        add(rows);
    }

    public JRowPanel() {
        this(new FlowLayout(FlowLayout.LEADING));
    }

    private int currentRowSize = 0;
    private Box currentRow = null;
    public JRowPanel append(int maxRowSize, int componentSize, Component c) {
        if(currentRow == null) {
            currentRow = Box.createHorizontalBox();
            rows.add(currentRow);
        }
        if(currentRowSize + componentSize > maxRowSize) {
            currentRow = Box.createHorizontalBox();
            currentRow.add(c);
            rows.add(currentRow);
            currentRowSize = 0;
        } else {
            currentRowSize += componentSize;
            currentRow.add(c);
        }
        return this;
    }
    
    public JRowPanel addRows(Component... components) {
        for (int i = 0; i < components.length; i++) {
            Component component = components[i];
            addRow(component);
        }
        return this;
    }
    
    public void createRowWithComponentCollection(Collection<? extends Component> components) {
        Box box = Box.createHorizontalBox();
        for (Component component : components) {
            box.add(component);
        }
        rows.add(box);
    }
    
    public JComponent createScroller() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(this, BorderLayout.LINE_START);
        return new JScrollPane(panel);
    }

    /**
     * Add a row of components where each component is wrapped in a titled box
     * @param stringComponentArray the title-component array
     * @return  this
     */
    public JRowPanel row(Object... stringComponentArray) {
        Box row = Box.createHorizontalBox();
        for (int i= 0; i < stringComponentArray.length; i+=2) {
            String title = (String) stringComponentArray[i];
            Component component = (Component) stringComponentArray[i+1];
            JPanel wrapper = new JPanel(new GridLayout(1, 1));
            wrapper.setBorder(BorderFactory.createTitledBorder(title));
            wrapper.add(component);
            row.add(wrapper);
        }
        rows.add(row);
        return this;
    }

    public JRowPanel fixedRow(Component... components) {
        JPanel row = new JPanel(new GridLayout(1, components.length));
        for (int i = 0; i < components.length; i++) {
            Component component = components[i];
            row.add(component);
        }
        rows.add(row);
        return this;
    }
    
    public JRowPanel flowingRow(Component... components) {
        JPanel row = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
        for (int i = 0; i < components.length; i++) {
            Component component = components[i];
            row.add(component);
        }
        rows.add(row);
        return this;
    }

    /**
     * Create a row with fixed cell size
     * @param stringComponentArray the title-component array
     * @return this
     */
    public JRowPanel fixedRow(Object... stringComponentArray) {
        JPanel row = new JPanel(new GridLayout(1, stringComponentArray.length / 2));
        for(int i = 0; i < stringComponentArray.length; i+=2) {
            String title = (String) stringComponentArray[i];
            Component component = (Component) stringComponentArray[i+1];
            JPanel wrapper = new JPanel(new GridLayout(1, 1));
            wrapper.add(component);
            wrapper.setBorder(BorderFactory.createTitledBorder(title));
            row.add(wrapper);
        }
        rows.add(row);
        return this;
    }

    public JRowPanel addRow(Component... components) {
        Box row = Box.createHorizontalBox();
        for (int i = 0; i < components.length; i++) {
            Component component = components[i];
            row.add(component);
        }
        rows.add(row);
        return this;
    }

    public JRowPanel emptyRow(int height) {
        return addRow(Box.createVerticalStrut(height));
    }

    public JRowPanel separator() {
        return addRow(new JSeparator(JSeparator.HORIZONTAL));
    }

    public Component getTitledItem(String string) {
        ListExt<Component> list = new LinkedListExt<Component>();
        list.add(this);
        while(!list.isEmpty()) {
            Component c = list.pop();
            if(string.equals(c.getName())) return c;
            if(c instanceof JComponent) {
                JComponent jc = (JComponent) c;
                Border border = jc.getBorder();
                if(border instanceof TitledBorder) {
                    TitledBorder titled = (TitledBorder) border;
                    if(string.equals(titled.getTitle())) return c;
                }
            }
            if(c instanceof Container) {
                Container cont = (Container) c;
                if(cont.getComponentCount() != 0) {
                    list.addAll(cont.getComponents());
                }
            }
        }
        return null;
    }
}
